﻿using BCCommon;
using BCCommon.Enums;
using BCData.Trading.SaleShoppingCart;
using BCDto.Trading.SaleShoppingCart;
using BCEntity.Trading.SaleShoppingCart;
using BCEntity.Common.EntityNameConst;
using BCService.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BCService.Trading.SaleGoods.SaleGoods;
using BCCommon.NPinyin;
using BCDto.Trading.SaleGoods.SaleGoodsNorm;

namespace BCService.Trading.SaleShoppingCart
{
    public class SaleShoppingCartService : ISaleShoppingCartService
    {
        private readonly IDatabaseContext databaseContext;
        private readonly IApplicationContextService applicationContextService;
        private readonly IRedisService redisService;
        private readonly ISaleShoppingCartData saleShoppingCartData;
        private readonly ISaleGoodsService saleGoodsService;
        private readonly string key = string.Format("{0}", EntityNameConst.SaleShoppingCartEntity);

        public SaleShoppingCartService(IDatabaseContext databaseContext,
            IApplicationContextService applicationContextService,
            IRedisService redisService,
            ISaleShoppingCartData saleShoppingCartData,
            ISaleGoodsService saleGoodsService)
        {
            this.databaseContext = databaseContext;
            this.applicationContextService = applicationContextService;
            this.redisService = redisService;
            this.saleShoppingCartData = saleShoppingCartData;
            this.saleGoodsService = saleGoodsService;
        }

        #region 检查销售购物车是否存在
        public bool Exists(long saleShoppingCartId)
        {
            return this.saleShoppingCartData.Exists(saleShoppingCartId).GetAwaiter().GetResult();
        }
        #endregion

        #region 添加销售购物车
        public SaleShoppingCartDto Add(SaleShoppingCartRequestDto requestDto)
        {
            if (requestDto.SaleGoodsNormId == 0)
            {
                throw new ArgumentException("商品信息错误!");
            }

            var goodsNormDto = this.saleGoodsService.GetGoodsNorm(requestDto.SaleGoodsNormId);
            if (goodsNormDto == null)
            {
                throw new ArgumentException("商品款式信息不存在!");
            }
            var goodsDto = this.saleGoodsService.Get(goodsNormDto.SaleGoodsId);
            if (goodsDto == null)
            {
                throw new ArgumentException("商品信息不存在!");
            }
            if (!goodsDto.Enabled)
            {
                throw new ArgumentException("此商品已下架!");
            }
            if (!goodsNormDto.Enabled)
            {
                throw new ArgumentException("此商品款式已下架!");
            }

            var shoppingCartList = this.GetList(applicationContextService.User.UserId);
            if (shoppingCartList.Any(p => p.SaleGoodsNormId == requestDto.SaleGoodsNormId))
            {
                var shoppingCartDto = shoppingCartList.Single(p => p.SaleGoodsNormId == requestDto.SaleGoodsNormId);
                shoppingCartDto.SaleCount = shoppingCartDto.SaleCount + requestDto.SaleCount;

                if (!goodsNormDto.HasBargain)
                {
                    var entity = shoppingCartDto.As<SaleShoppingCartEntity>();
                    this.CalculateStepAmount(entity, goodsNormDto);
                    var result = this.saleShoppingCartData.Update(entity).Result;
                    if (result==null)
                    {
                        throw new ArgumentException("添加购物车失败!");
                    }
                    string cacheKey = this.redisService.GetKey(key, shoppingCartDto.SaleShoppingCartId);
                    this.redisService.DeleteMultipleKey(cacheKey,false);
                    return result.As<SaleShoppingCartDto>();
                }
                else {
                    var result = this.saleShoppingCartData.UpdateSaleCount(shoppingCartDto.SaleShoppingCartId, shoppingCartDto.SaleCount).Result;
                    if (!result)
                    {
                        throw new ArgumentException("添加购物车失败!");
                    }
                    string cacheKey = this.redisService.GetKey(key, shoppingCartDto.SaleShoppingCartId);
                    this.redisService.DeleteAsync(cacheKey);
                    return this.Get(shoppingCartDto.SaleShoppingCartId);
                }
            }
            else
            {
                #region 新添加购物车商品
                var entity = requestDto.As<SaleShoppingCartEntity>();
                entity.UserId = applicationContextService.User.UserId;
                entity.SaleGoodsId = goodsNormDto.SaleGoodsId;
                entity.SaleGoodsCategoryId = goodsNormDto.SaleGoodsCategoryId;
                entity.CategoryName = goodsNormDto.CategoryName;
                entity.CategoryNamePinyin = Pinyin.GetCompactPinyin(entity.CategoryName);
                entity.GoodsName = goodsNormDto.GoodsName;
                entity.GoodsNamePinyin = Pinyin.GetCompactPinyin(entity.GoodsName);
                entity.Sku = goodsNormDto.Sku;
                entity.NormName = goodsNormDto.NormName;
                entity.NormNamePinyin = goodsNormDto.NormNamePinyin;
                entity.NormNo = goodsNormDto.NormNo;
                entity.MainImage = goodsNormDto.MainImage;
                entity.SaleUnit = goodsNormDto.SaleUnit;

                if (!goodsNormDto.HasBargain)
                {
                    this.CalculateStepAmount(entity, goodsNormDto);
                }
                if (entity.SaleCount == 0)
                {
                    entity.SaleCount = 1;
                }
                #endregion
                return this.saleShoppingCartData.Add(entity).GetAwaiter().GetResult().As<SaleShoppingCartDto>();
            }
        }
        #endregion

        #region 计算阶梯价格
        private void CalculateStepAmount(SaleShoppingCartEntity entity, SaleGoodsNormDto goodsNormDto)
        {
            decimal saleAmount = goodsNormDto.SaleAmount.HasValue ? goodsNormDto.SaleAmount.Value : 0;
            if (goodsNormDto.HasStepPrice)
            {
                if (goodsNormDto.StepOneEndNumber.HasValue && goodsNormDto.StepOneEndNumber >= entity.SaleCount && goodsNormDto.StepOnePrice.HasValue)
                {
                    saleAmount = goodsNormDto.StepOnePrice.Value;
                }
                else if (goodsNormDto.StepTwoEndNumber.HasValue && goodsNormDto.StepTwoEndNumber >= entity.SaleCount && goodsNormDto.StepTwoPrice.HasValue)
                {
                    saleAmount = goodsNormDto.StepTwoPrice.Value;
                }
                else if (goodsNormDto.StepThreeEndNumber.HasValue && goodsNormDto.StepThreeEndNumber >= entity.SaleCount && goodsNormDto.StepThreePrice.HasValue)
                {
                    saleAmount = goodsNormDto.StepThreePrice.Value;
                }
                else if (goodsNormDto.StepThreeStartNumber.HasValue && !goodsNormDto.StepThreeEndNumber.HasValue && goodsNormDto.StepThreeStartNumber <= entity.SaleCount && goodsNormDto.StepThreePrice.HasValue)
                {
                    saleAmount = goodsNormDto.StepThreePrice.Value;
                }
                else if (goodsNormDto.StepThreeStartNumber.HasValue && !goodsNormDto.StepThreeEndNumber.HasValue && goodsNormDto.StepThreeStartNumber > entity.SaleCount && goodsNormDto.StepTwoPrice.HasValue)
                {
                    saleAmount = goodsNormDto.StepTwoPrice.Value;
                }
                else if (goodsNormDto.StepTwoStartNumber.HasValue && !goodsNormDto.StepTwoEndNumber.HasValue && goodsNormDto.StepTwoStartNumber <= entity.SaleCount && goodsNormDto.StepTwoPrice.HasValue)
                {
                    saleAmount = goodsNormDto.StepTwoPrice.Value;
                }
                else if (goodsNormDto.StepTwoStartNumber.HasValue && !goodsNormDto.StepTwoEndNumber.HasValue && goodsNormDto.StepTwoStartNumber > entity.SaleCount && goodsNormDto.StepOnePrice.HasValue)
                {
                    saleAmount = goodsNormDto.StepOnePrice.Value;
                }
            }
            entity.SaleAmount = saleAmount;
        }
        #endregion

        #region 修改销售购物车
        public SaleShoppingCartDto Update(SaleShoppingCartPutDto putDto)
        {
            if (!this.Exists(putDto.SaleShoppingCartId))
            {
                throw new ArgumentException("此记录不存在!");
            }
            
            var oldDto = this.Get(putDto.SaleShoppingCartId);

            if (oldDto.HasCreateSaleContract)
            {
                throw new ArgumentException("操作错误,此购物车商品已生成订单!");
            }
            if (applicationContextService.Admin == null)
            {
                if (oldDto.UserId != applicationContextService.User.UserId)
                {
                    throw new ArgumentException("您无法修改他人购物车商品!");
                }
            }

            var entity = putDto.As<SaleShoppingCartEntity>();

            var result = this.saleShoppingCartData.Update(entity).GetAwaiter().GetResult().As<SaleShoppingCartDto>();
            string cacheKey = this.redisService.GetKey(key, entity.SaleShoppingCartId);
            this.redisService.DeleteMultipleKey(cacheKey, false);
            cacheKey = this.redisService.GetSingleRootKey(key, "userId", oldDto.UserId);
            this.redisService.DeleteMultipleKey(cacheKey, false);
            return result;
        }
        #endregion

        #region 修改购物车商品购买数量
        public bool UpdateSaleCount(long saleShoppingCartId, int saleCount)
        {
            if (!this.Exists(saleShoppingCartId))
            {
                throw new ArgumentException("此记录不存在!");
            }
            var oldDto = this.Get(saleShoppingCartId);
            if (oldDto.HasCreateSaleContract)
            {
                throw new ArgumentException("操作错误,此购物车商品已生成订单!");
            }
            if (oldDto.UserId != applicationContextService.User.UserId)
            {
                throw new ArgumentException("您无法修改他人购物车商品!");
            }
            var result = this.saleShoppingCartData.UpdateSaleCount(saleShoppingCartId, saleCount).GetAwaiter().GetResult();

            string cacheKey = this.redisService.GetKey(key, saleShoppingCartId);
            this.redisService.DeleteMultipleKey(cacheKey, false);
            cacheKey = this.redisService.GetSingleRootKey(key,"userId", oldDto.UserId);
            this.redisService.DeleteMultipleKey(cacheKey,false);
            return result;
        }
        #endregion

        #region 删除销售购物车
        public bool Delete(long saleShoppingCartId)
        {
            if (!this.Exists(saleShoppingCartId))
            {
                throw new ArgumentException("此记录不存在!");
            }
            var oldDto = this.Get(saleShoppingCartId);
            if (oldDto.HasCreateSaleContract)
            {
                throw new ArgumentException("操作错误,此购物车商品已生成订单!");
            }
            if (oldDto.UserId != applicationContextService.User.UserId)
            {
                throw new ArgumentException("您无权删除他人购物车商品!");
            }
            var result = this.saleShoppingCartData.Delete(saleShoppingCartId).GetAwaiter().GetResult();
            string cacheKey = this.redisService.GetKey(key, saleShoppingCartId);
            this.redisService.DeleteAsync(cacheKey);
            cacheKey = this.redisService.GetSingleRootKey(key, "userId", oldDto.UserId);
            this.redisService.DeleteMultipleKey(cacheKey, false);
            return result;
        }
        #endregion

        #region 获取销售购物车
        public SaleShoppingCartDto Get(long saleShoppingCartId)
        {
            string cacheKey = this.redisService.GetKey(key, saleShoppingCartId);
            var result = this.redisService.TryGet(cacheKey, () =>
            {
                var data = this.saleShoppingCartData.GetEntity(saleShoppingCartId).GetAwaiter().GetResult();
                return data;
            }, TimeSpan.FromMinutes(30));
            return result.As<SaleShoppingCartDto>();
        }
        #endregion

        #region 获取销售购物车列表
        public IEnumerable<SaleShoppingCartDto> GetList(long userId)
        {
            string cacheKey = this.redisService.GetKey(key, userId);
            var result = this.redisService.TryGet(cacheKey, () =>
            {
                return this.saleShoppingCartData.GetList(userId).GetAwaiter().GetResult();
            }, TimeSpan.FromMinutes(30));
            return result.As<IEnumerable<SaleShoppingCartDto>>();
        }
        #endregion

        #region 获取销售购物车数量
        public int Count(long userId)
        {
            return this.saleShoppingCartData.Count(userId).GetAwaiter().GetResult();
        }
        #endregion

        #region 获取销售购物车分页
        public PageableList<SaleShoppingCartDto> Query(long userId, DateTime? start, DateTime? end, string sortName, bool? ascending, int pageIndex, int pageSize)
        {
            string cacheKey = this.redisService.GetKey(key, userId, start, end, sortName, ascending, pageIndex, pageSize);
            var result = this.redisService.TryGet(cacheKey, () =>
            {
                var data = this.saleShoppingCartData.Query(userId, start, end, sortName, ascending, pageIndex, pageSize).GetAwaiter().GetResult();
                return new PageableList<SaleShoppingCartDto>
                {
                    Count = data.Item2,
                    Items = data.Item1.As<IEnumerable<SaleShoppingCartDto>>(),
                    PageIndex = pageIndex,
                    PageSize = pageSize,
                    ServerTime = DateTime.Now
                };
            }, TimeSpan.FromMinutes(30));

            return result;
        }
        #endregion

        #region 合计销售商品金额
        public decimal SumSaleGoodsAmount(List<long> ids)
        {
            return this.saleShoppingCartData.SumSaleGoodsAmount(ids).Result;
        }
        #endregion
    }
}